﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Input;
using System.IO;

namespace December
{
    public class XNACharHelper
    {
        public static fontCharacter FONT_CHARACTER { get; set; }
        public bool DRAW_LINE_DRAG_CURSOR { get; set; }

        fontLine LINE_X;
        fontLine LINE_LEADING;
        fontLine LINE_X_HEIGHT;
        fontLine LINE_CAP_HEIGHT;
        fontLine LINE_ASCENDER_HEIGHT;
        fontLine LINE_DESCENDER_HEIGHT;
        fontLine LINE_WIDTH;
        fontLine LINE_Y;

        public int PREVIEW_WIDTH, PREVIEW_HEIGHT;

        Texture2D LINE_TEXTURE;
        SpriteFont SPRITE_FONT;

        public static bool DRAW_LINES = true;
        public Camera2D CAMERA = new Camera2D();
        public Vector2 CHARACTER_POSITION = Vector2.Zero;

        Texture2D CHARACTER_TEXTURE;
        public static bool CHARACTER_CHANGED = true;
        private GraphicsDevice GRAPHICS;

        #region Constructor
        public XNACharHelper(int width, int height, GraphicsDevice graphics)
        {
            GRAPHICS = graphics;
            DRAW_LINE_DRAG_CURSOR = false;
            initEmptyLines();

            PREVIEW_WIDTH = width;
            PREVIEW_HEIGHT = height;
            CAMERA.init(PREVIEW_WIDTH, PREVIEW_HEIGHT);

            
        }
        #endregion

        #region LoadContent
        public void LoadContent(ContentManager content)
        {
            SPRITE_FONT = content.Load<SpriteFont>(@"Font\dummyFont");
            LINE_TEXTURE = content.Load<Texture2D>(@"Dummy\pixel");
        }

        public void LoadCharacterTexture(fontCharacter fc)
        {
            FONT_CHARACTER = fc;
            CHARACTER_TEXTURE = getTextureFromFile(FONT_CHARACTER.Image, GRAPHICS); 
            initLines();

            this.CHARACTER_POSITION = new Vector2(LINE_Y.X - FONT_CHARACTER.AnchorPointX, LINE_X.Y - FONT_CHARACTER.AnchorPointY);
        }
        #endregion

        #region Update
        MouseState oldState;
        public void Update(MouseState mouseState, int mousedelta)
        {
            if(CHARACTER_CHANGED)
            {
                CHARACTER_TEXTURE = getTextureFromFile(FONT_CHARACTER.Image,GRAPHICS);
                updateCharPosition();
                updateWidthLine();
                CHARACTER_CHANGED = false;
            }

            Matrix inverse = Matrix.Invert(CAMERA.GetTransformation());
            Vector2 mousePosition = Vector2.Transform(new Vector2(mouseState.X, mouseState.Y), inverse);
            Rectangle mouseRect = new Rectangle((int)mousePosition.X, (int)mousePosition.Y, 1, 1);

            if (DRAW_LINES)
            {
                mouseClick_MoveWidthLine(LINE_WIDTH, ref mouseState, ref mouseRect);
            }

            #region scaling
            if (mousedelta > 0)
            {
                CAMERA.Zoom += 0.1f;
            }
            if (mousedelta < 0)
            {
                CAMERA.Zoom -= 0.1f;
            }
            #endregion
            oldState = mouseState;
        }

        private void updateWidthLine()
        {
            LINE_WIDTH.init(CHARACTER_POSITION.X + FONT_CHARACTER.Width, 5, 1, this.PREVIEW_HEIGHT - 10);
        }

        private void mouseClick_MoveWidthLine(fontLine line, ref MouseState mouseState, ref Rectangle mouseRect)
        {
            if (mouseRect.Intersects(line.sourceRect))
            {
                line.color = Color.Red;
            }
            else
            {
                line.color = Color.Black;
            }

            if (mouseState.LeftButton == ButtonState.Pressed)
            {
                if (mouseRect.Intersects(line.sourceRect))
                {
                    line.move = true;
                    line.color = Color.Red;
                    DRAW_LINE_DRAG_CURSOR = true;
                }
                if (line.move)
                {
                    FONT_CHARACTER.Width = mouseRect.X - CHARACTER_POSITION.X;
                    line.X = mouseRect.X;
                }
                XNAHelper.REINIT_PREVIEWCHARACTERS = true;
            }

            if (mouseState.LeftButton == ButtonState.Released)
            {
                line.move = false;
                if (oldState.LeftButton == ButtonState.Pressed && mouseState.LeftButton == ButtonState.Released)
                {
                    line.color = Color.Black;
                    DRAW_LINE_DRAG_CURSOR = false;
                }
            }
        }

        public void updateResize(int newWidth, int newHeight)
        {
            this.PREVIEW_WIDTH = newWidth;
            this.PREVIEW_HEIGHT = newHeight;

            initLines(); 
            updateCharPosition();
            updateWidthLine();
        }

        private void updateCharPosition()
        {
            this.CHARACTER_POSITION = new Vector2(LINE_Y.X - FONT_CHARACTER.AnchorPointX, LINE_X.Y - FONT_CHARACTER.AnchorPointY);
        }
        #endregion

        #region Draw
        public void Draw(SpriteBatch spriteBatch)
        {
            CAMERA.Pos = new Vector2(PREVIEW_WIDTH, PREVIEW_HEIGHT);
            SamplerState st = new SamplerState();
            if (CAMERA.Zoom > 2f)
                st = SamplerState.PointClamp;
            if (CAMERA.Zoom <= 2f)
                st = SamplerState.LinearClamp;

            spriteBatch.Begin(SpriteSortMode.BackToFront, null, st, null, null, null, CAMERA.GetTransformation());

            DrawCharacter(spriteBatch);
            if (DRAW_LINES)
            {
                DrawLines(spriteBatch);
            }

            spriteBatch.End();
        }

        private void DrawLines(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(LINE_TEXTURE, LINE_X.sourceRect, LINE_X.color);
            spriteBatch.Draw(LINE_TEXTURE, LINE_LEADING.sourceRect, LINE_LEADING.color);
            spriteBatch.Draw(LINE_TEXTURE, LINE_X_HEIGHT.sourceRect, LINE_X_HEIGHT.color);
            spriteBatch.Draw(LINE_TEXTURE, LINE_CAP_HEIGHT.sourceRect, LINE_CAP_HEIGHT.color);
            spriteBatch.Draw(LINE_TEXTURE, LINE_ASCENDER_HEIGHT.sourceRect, LINE_ASCENDER_HEIGHT.color);
            spriteBatch.Draw(LINE_TEXTURE, LINE_DESCENDER_HEIGHT.sourceRect, LINE_DESCENDER_HEIGHT.color);
            spriteBatch.Draw(LINE_TEXTURE, LINE_WIDTH.sourceRect, LINE_WIDTH.color);
            spriteBatch.Draw(LINE_TEXTURE, LINE_Y.sourceRect, LINE_Y.color);
        }

        private void DrawCharacter(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(CHARACTER_TEXTURE, CHARACTER_POSITION, Color.White);
        }
        #endregion

        #region Initialization (LINES)
        private void initEmptyLines()
        {
            LINE_X = new fontLine();
            LINE_Y = new fontLine();
            LINE_LEADING = new fontLine();
            LINE_X_HEIGHT = new fontLine();
            LINE_CAP_HEIGHT = new fontLine();
            LINE_ASCENDER_HEIGHT = new fontLine();
            LINE_DESCENDER_HEIGHT = new fontLine();
            LINE_WIDTH = new fontLine();

            LINE_X.color = Color.Black;
            LINE_Y.color = Color.Black;
            LINE_LEADING.color = Color.Black;
            LINE_X_HEIGHT.color = Color.Black;
            LINE_CAP_HEIGHT.color = Color.Black;
            LINE_ASCENDER_HEIGHT.color = Color.Black;
            LINE_DESCENDER_HEIGHT.color = Color.Black;
            LINE_WIDTH.color = Color.Black;
        }


        private void initLines()
        {
            //base lines
            LINE_X.init(5, this.PREVIEW_HEIGHT / 2, this.PREVIEW_WIDTH - 10, 1);
            LINE_Y.init(PREVIEW_WIDTH/2, 5, 1, this.PREVIEW_HEIGHT - 10);
            //font lines
            LINE_LEADING.init(LINE_X.X, LINE_X.Y + mainform.NEW_FONT.LEADING + mainform.NEW_FONT.DESCENDER_HEIGHT, LINE_X.Width, 1);
            LINE_X_HEIGHT.init(LINE_X.X, LINE_X.Y - mainform.NEW_FONT.X_HEIGHT, LINE_X.Width, 1);
            LINE_CAP_HEIGHT.init(LINE_X.X, LINE_X.Y - mainform.NEW_FONT.CAP_HEIGHT, LINE_X.Width, 1);
            LINE_ASCENDER_HEIGHT.init(LINE_X.X, LINE_X.Y - mainform.NEW_FONT.ASCENDER_HEIGHT, LINE_X.Width, 1);
            LINE_DESCENDER_HEIGHT.init(LINE_X.X, LINE_X.Y + mainform.NEW_FONT.DESCENDER_HEIGHT, LINE_X.Width, 1);
            //char specific line
            updateWidthLine();
        }
        #endregion


        private Texture2D getTextureFromFile(string path, GraphicsDevice graphics)
        {
            FileStream fs = new FileStream(path, FileMode.Open);
            Texture2D t2d = Texture2D.FromStream(graphics, fs);
            fs.Close();
            return t2d;
        }
    }
}
